/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.clinicalsummary.web.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.api.context.Context;
import org.openmrs.module.clinicalsummary.FileUtils;
import org.openmrs.module.clinicalsummary.SummaryConstants;
import org.openmrs.util.OpenmrsUtil;
import org.openmrs.web.WebConstants;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 */
@Controller
@RequestMapping("/module/clinicalsummary/summaryDownload")
public class SummaryDownloadFormController {
	
	private static final Log log = LogFactory.getLog(SummaryDownloadFormController.class);
	
	private static final int BUFFER_SIZE = 4096;
	
	private static final String ZIP_FILE = ".zip";
	
	@RequestMapping(method = RequestMethod.GET)
	public void preparePage(ModelMap map) {
		if (Context.isAuthenticated()) {
			File parentSecretFile = OpenmrsUtil.getDirectoryInApplicationDataDirectory(SummaryConstants.ENCRYPTION_LOCATION);
			String[] filenames = parentSecretFile.list();
			map.addAttribute("secretFiles", filenames);
		}
	}
	
	@RequestMapping(method = RequestMethod.POST)
	public String downloadSummaries(@RequestParam(required = true, value = "password") String password,
	                                @RequestParam(required = true, value = "passphrase") String passphrase,
	                                HttpServletRequest request, HttpServletResponse response) {
		
		HttpSession httpSession = request.getSession();
		
		if (Context.isAuthenticated())
			// user must be authenticated (avoids auth errors)
			try {
				httpSession.setMaxInactiveInterval(-1); // don't let the session expire
				httpSession.removeAttribute(WebConstants.OPENMRS_ERROR_ATTR);
				
				File generatedFolder = OpenmrsUtil
				        .getDirectoryInApplicationDataDirectory(SummaryConstants.GENERATED_PDF_LOCATION);
				
				String time = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
				String filename = "Summaries_" + time;
				
				File zippedFile = File.createTempFile("Summary", ZIP_FILE);
				BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(zippedFile));
				
				if (StringUtils.isBlank(password))
					throw new IOException("Both password and passphrase can't be blank");
				
				if (StringUtils.isBlank(passphrase))
					throw new IOException("Both password and passphrase can't be blank");
				
				FileUtils.createIndexFile("summaryindex.sql");
				FileUtils.deflateSummaries(outputStream, generatedFolder.getAbsolutePath(), password, passphrase, filename);
				
				//Prepare response
				response.setHeader("Content-Disposition", "attachment; filename=" + filename + ".zip");
				response.setHeader("Content-Length", String.valueOf(zippedFile.length()));
				response.setContentType("application/zip");
				response.flushBuffer();
				
				BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(zippedFile));
				
				ReadableByteChannel input = Channels.newChannel(inputStream);
				WritableByteChannel output = Channels.newChannel(response.getOutputStream());
				ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
				
				while (input.read(buffer) != -1) {
					buffer.flip();
					output.write(buffer);
					buffer.clear();
				}
				
				input.close();
				output.close();
			}
			catch (Exception e) {
				String message = "Failed generating collection of summaries for standalone sites. Please check the log file to see the problem(s)";
				httpSession.setAttribute(WebConstants.OPENMRS_ERROR_ATTR, message);
				
				log.error("Failed generating collection of summaries for standalone sites ...", e);
			}
		return "redirect:summaryDownload.form";
	}
}
